package com.future.message.Service.Impl;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.SCPInputStream;
import com.future.message.Mapper.DataMapper;
import com.future.message.Mapper.IndexMapper;
import com.future.message.Mapper.RelevantReportMapper;
import com.future.message.Mapper.UserMapper;
import com.future.message.Service.FileService;
import com.future.message.Service.IndexService;
import com.future.message.Utils.ResponseResult;
import com.future.message.Utils.Utils;
import com.future.message.Utils.toZipUtils;
import com.future.message.Utils.uploadUtil;
import com.future.message.pojo.Data;
import com.future.message.pojo.Index;
import com.future.message.pojo.RelevantReport;
import com.future.message.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class FileServiceImpl implements FileService {
    @Resource
    UserMapper userMapper;
    @Resource
    DataMapper dataMapper;
    @Resource
    RelevantReportMapper relevantReportMapper;
    @Resource
    IndexMapper indexMapper;

    //项目根路径下的目录:springboot默认static
    public final static String UPLOAD_PATH_PREFIX="/static/upload/";
    //访问目录:
    public final String DOWNLOAD_PATH_PREFIX="/upload";

    @Override
    public String fileUpLoad(MultipartFile file) {
        return null;
    }


    @Override
    public ResponseResult uploadRelevantFile(MultipartFile file, Integer userId, Integer relevantReportId){
        RelevantReport relevantReport=relevantReportMapper.findRelevantReportById(relevantReportId);
        if (relevantReport == null) {
            return ResponseResult.error("填报关联不存在");
        }
        if(!userId.equals(relevantReport.getUserId())){
            return ResponseResult.error("你不能上传别人的填报关联");
        }
        ResponseResult responseResult=new ResponseResult();
        int maxSize = 1024*1024*1024;    //上传最大为100MB
        if (file.getSize()>maxSize) {
            responseResult.setMessage("最大上传限制100Mb");
            return responseResult;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        File targetFile=null;
        String url="";//返回存储路径
        String fileName=file.getOriginalFilename();//获取文件名加后缀
        if(fileName!=null&&fileName!=""){
            String fileF = fileName.substring(fileName.lastIndexOf("."), fileName.length());//文件后缀
            if ((fileF.equals(".asp") || fileF.equals(".php") ||
                    fileF.equals(".aspx") || fileF.equals(".cgi")||
                    fileF.equals(".exe")||fileF.equals(".html")||
                    fileF.equals(".htm")||fileF.equals(".jsp"))) {
                return ResponseResult.error("请规范格式");
            }

            User user=userMapper.findUserById(userId);
            //先判断这个用户是否有重名,然后在写
            String userPath=UPLOAD_PATH_PREFIX+user.getUserId()+"/"+relevantReport.getRelevantReportId();
//            //新的文件名
//            fileName=new Date().getTime()+"_"+new Random().nextInt(1000)+fileF;
            //获取文件夹路径
            String realPath=System.getProperty("user.dir")+userPath;
            File file1=new File(realPath);
            System.out.println(file1.getAbsolutePath());
            //如果文件夹不存在则创建
            if(!file1.exists()  && !file1.isDirectory()){
                file1.mkdirs();
            }
            //判断文件是否存在
            HashMap<String,Object> filesName= uploadUtil.getFilesName(realPath+"/"+fileName,fileName);
            System.out.println(filesName);
            System.out.println(filesName.get("retType"));
            //将图片存入文件夹
            targetFile = new File(file1, fileName);
            try {
                //将上传的文件写到服务器上指定的文件。
                file.transferTo(targetFile);
                //生成文件地址
                url=realPath+"/"+fileName;
                log.info(url);
                responseResult.setCode(200);
                responseResult.setMessage("文件上传成功");
                System.out.println("文件上传成功 url:"+url);
                map.put("url", url);
                responseResult.setObject(map);
            } catch (Exception e) {
                e.printStackTrace();
                responseResult.setMessage("系统异常，文件上传失败");
            }
        }
        return responseResult;
    }

    @Override
    public ResponseResult uploadIndexFile(MultipartFile file, Integer indexId) {
        Index index=indexMapper.findIndexById(indexId);
        if(index==null){
            return ResponseResult.error("指标不存在");
        }
        ResponseResult responseResult=new ResponseResult();
        int maxSize = 1024*1024*1024;    //上传最大为100MB
        if (file.getSize()>maxSize) {
            responseResult.setMessage("最大上传限制100Mb");
            return responseResult;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        File targetFile=null;
        String url="";//返回存储路径
        String fileName=file.getOriginalFilename();//获取文件名加后缀
        if(fileName!=null&&fileName!=""){
            String fileF = fileName.substring(fileName.lastIndexOf("."), fileName.length());//文件后缀
            if ((fileF.equals(".asp") || fileF.equals(".php") ||
                    fileF.equals(".aspx") || fileF.equals(".cgi")||
                    fileF.equals(".exe")||fileF.equals(".html")||
                    fileF.equals(".htm")||fileF.equals(".jsp"))) {
                return ResponseResult.error("请规范格式");
            }
            //先判断这个用户是否有重名,然后在写
            String userPath=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
            String realPath=System.getProperty("user.dir")+userPath;
            File file1=new File(realPath);
            System.out.println(file1.getAbsolutePath());
            //如果文件夹不存在则创建
            if(!file1.exists()  && !file1.isDirectory()){
                file1.mkdirs();
            }
            //判断文件是否存在
            HashMap<String,Object> filesName= uploadUtil.getFilesName(realPath+"/"+fileName,fileName);
            System.out.println(filesName);
            System.out.println(filesName.get("retType"));
            //将图片存入文件夹
            targetFile = new File(file1, fileName);
            try {
                //将上传的文件写到服务器上指定的文件。
                file.transferTo(targetFile);
                //生成文件地址
                url=realPath+"/"+fileName;
                log.info(url);
                responseResult.setCode(200);
                responseResult.setMessage("文件上传成功");
                System.out.println("文件上传成功 url:"+url);
                map.put("url", url);
                responseResult.setObject(map);
            } catch (Exception e) {
                e.printStackTrace();
                responseResult.setMessage("系统异常，文件上传失败");
            }
        }
        return responseResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult batchUploadFile(MultipartFile [] file,Integer userId,Integer relevantReportId) {
        ResponseResult responseResult=null;
        if(file!=null){
            for(MultipartFile x:file){
                responseResult= uploadRelevantFile(x,userId,relevantReportId);
                String sc=x.getOriginalFilename();
                System.out.println(sc);
            }
        }
        return responseResult;
    }

    @Override
    public ResponseResult batchUploadIndexFile(MultipartFile[] file, Integer indexId) {
        ResponseResult responseResult=null;
        if(file!=null){
            for(MultipartFile x:file){
                responseResult= uploadIndexFile(x,indexId);
                String sc=x.getOriginalFilename();
                System.out.println(sc);
            }
        }
        return responseResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult deleteFile(String fileName,Integer dataId,Integer userId) {
        Data data=dataMapper.findDataById(dataId);
        if (data == null) {
            return ResponseResult.error("不存在该数据");
        }
        User user=userMapper.findUserById(data.getUserId());
        if (user == null) {
            return ResponseResult.error("该部门已被删除");
        }
        User user1=userMapper.findUserById(userId);
        if(user1==null){
            return ResponseResult.error("该用户不存在");
        }
        RelevantReport relevantReport= relevantReportMapper.findRelevantReportById(data.getRelevantReportId());
        if (relevantReport == null) {
            return ResponseResult.error("不存在该填报关联");
        }
        //若当前登录id和填写数据id相同则可以删除
        if(user.getUserId().equals(user1.getUserId())){
            String userPath=UPLOAD_PATH_PREFIX+user.getUserId();
            String realPath=System.getProperty("user.dir")+userPath+"/"+relevantReport.getRelevantReportId();
            File file=new File(realPath+"/"+fileName);
            ArrayList<String> ss=Utils.splitAdd(data.getSrc());
            ss.remove(fileName);
            dataMapper.updateSrc(dataId,ss.toString());
            if(file.exists()&&file.isFile()){
               Boolean q= file.delete();
                File file1=new File(realPath);
                Boolean a= file1.delete();//删除文件夹
                return ResponseResult.success("删除成功",q);
            }else{
                return ResponseResult.error("文件不存在");
            }
        }
        //如果不是本人,那么只有管理员才能删除
        if(!user.getUserId().equals(user1.getUserId()) &&user1.getGrade()==1){
            String userPath=UPLOAD_PATH_PREFIX+user.getUserId();
            String realPath=System.getProperty("user.dir")+userPath;
            File file=new File(realPath+"/"+fileName);
            ArrayList<String> ss=Utils.splitAdd(data.getSrc());
            ss.remove(fileName);
            dataMapper.updateSrc(dataId,ss.toString());
            if(file.exists()&&file.isFile()){
                File file1=new File(realPath);
                Boolean a= file1.delete();//删除文件夹
                Boolean xs= file.delete();
                return ResponseResult.success("删除成功",xs);
            }else{
                return ResponseResult.error("文件不存在");
            }
        }
        return ResponseResult.error("你不是管理员或本人,不能删除别人的文件");
    }

    @Override
    public ResponseResult deleteIndexFile(String fileName, Integer indexId) {
        Index index=indexMapper.findIndexById(indexId);
        if(index==null){
            return ResponseResult.error("该指标不存在");
        }
            String userPath=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
            String realPath=System.getProperty("user.dir")+userPath;
            File file=new File(realPath+"/"+fileName);
            ArrayList<String> ss=Utils.splitAdd(index.getData());
            if(file.exists()&&file.isFile()){
                Boolean q= file.delete();//确定文件夹路径
                ss.remove(fileName);
                indexMapper.updateData(indexId,ss.toString());
                File file1=new File(realPath);
                Boolean a= file1.delete();//删除文件夹
                log.info("删除指标模板成功,删除之后为: "+ss.toString());
                return ResponseResult.success("删除成功",q);
            }else{
                return ResponseResult.error("文件不存在");
            }
    }

    @Override
    public ResponseResult testUpload(MultipartFile file, HttpServletRequest request) {
        String realPath=System.getProperty("user.dir")+UPLOAD_PATH_PREFIX;
        File file1=new File(realPath);
        System.out.println(file1.getAbsolutePath());
        return null;
    }

    @Override
    public void downLoadRelevantFile(Integer userId, Integer relevantReportId, String fileName, HttpServletResponse response) {
        User user=userMapper.findUserById(userId);
        if(user==null){
            ResponseResult.out(response,ResponseResult.error("该用户不存在"));
            return;
        }
        RelevantReport relevantReport= relevantReportMapper.findRelevantReportById(relevantReportId);
        if (relevantReport == null) {
            ResponseResult.out(response,ResponseResult.error("不存在该填报关联"));
            return ;
        }
        User user1=userMapper.findUserById(relevantReport.getUserId());
        if (user1 == null) {
            ResponseResult.out(response,ResponseResult.error("该用户已被删除"));
            return;
        }
        String userPath=user.getUserId()+"/"+relevantReport.getRelevantReportId();
//        String realPath="/usr/local"+"/"+userPath+"/"+fileName;
//        String realPath2="/usr/local"+"/"+userPath;

        //==================================================
        String userPath1=UPLOAD_PATH_PREFIX+user1.getUserId()+"/"+relevantReport.getRelevantReportId();
        String realPath1=System.getProperty("user.dir")+userPath1+"/"+fileName;
        log.info(realPath1);
        File file = new File(realPath1);
        if (!file.exists()){
            log.info("文件不存在！！");
            ResponseResult.out(response,ResponseResult.error("文件不存在！"));
            return;
        }
        try{
            response.setCharacterEncoding("UTF-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        }catch (Exception e){
            log.info(e.getMessage());
            ResponseResult.out(response,ResponseResult.error("编码错误，请稍后重试！"));
            log.info(fileName+"编码错误");
            return;
        }

//        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
//                ContentDisposition.attachment()
//                        .filename(fileName, StandardCharsets.UTF_8)
//                        .build()
//                        .toString());
        response.setContentType("application/octet-stream");
        try (InputStream inputStream = new FileInputStream(file);
             ServletOutputStream outputStream = response.getOutputStream();) {
            byte []bytes = new byte[1024];

            int n;
            while((n = inputStream.read(bytes)) != -1)
            {
                outputStream.write(bytes,0,n);
            }
            log.info(userId+"用户在下载"+file.getAbsolutePath());
        } catch (Exception e){
            e.printStackTrace();
            log.info("下载文件出现严重异常!"+file.getName());
            ResponseResult.out(response,ResponseResult.error("文件下载出错，请稍后重试！"));
            return;
        }
        //==================================================
//        log.info(realPath);
//        //port:22是连接linux传输,3389是连接windos传输
//        Connection connection = new Connection("101.35.50.204",22);
//        //客户端要存储的下载文件的路径可以自己随便定义
//        File newFiles = new File(realPath2);
//        if(!newFiles.exists()){newFiles.mkdirs();}
//        File newFile=new File(realPath);
//        try(FileOutputStream fos = new FileOutputStream(newFile);) {
//            connection.connect();
//            boolean isAuthenticated = connection.authenticateWithPassword("root","Xyj20020815");
//            if(isAuthenticated){
//                SCPClient scpClient = connection.createSCPClient();
//                String userPath1=UPLOAD_PATH_PREFIX+user1.getUserId()+"/"+relevantReport.getRelevantReportId();
//                String realPath1=System.getProperty("user.dir")+userPath1+"/"+fileName;
//                //从目标文件服务器下载文件
//                SCPInputStream sis = scpClient.get(realPath1);
//                System.out.println(realPath1);
//                //先将远程服务器的文件下载到用户的电脑某个磁盘内
//                File f = new File("/usr/local");
//                if(!f.exists()){
//                    f.mkdirs();//不存在就创建文件夹
//                }
//                byte[] b = new byte[4096];
//                int i;
//                while ((i = sis.read(b)) != -1){
//                    fos.write(b,0, i);
//                }
//                fos.flush();
//                fos.close();
//                sis.close();
//                connection.close();
//                log.info("download ok");
//            }else{
//                log.info("建立连接失败");
//            }
//        } catch (IOException e) {
//            log.info("下载文件异常="+e.toString());
//        }
    }

    @Override
    public void downLoadIndexFile(Integer indexId, String fileName,HttpServletResponse response) {
        Index index=indexMapper.findIndexById(indexId);
        if(index==null){
            ResponseResult.out(response,ResponseResult.error("该指标不存在"));
            return;
        }
        //==================================================
        String userPath1=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
        String realPath1=System.getProperty("user.dir")+userPath1+"/"+fileName;
        log.info(realPath1);
        File file = new File(realPath1);
        if (!file.exists()){
            log.info("文件不存在！！");
            ResponseResult.out(response,ResponseResult.error("文件不存在！"));
            return;
        }
        try{
            response.setCharacterEncoding("UTF-8");
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        }catch (Exception e){
            log.info(e.getMessage());
            ResponseResult.out(response,ResponseResult.error("编码错误，请稍后重试！"));
            log.info(fileName+"编码错误");
            return;
        }
        response.setContentType("application/octet-stream");
        try (InputStream inputStream = new FileInputStream(file);
             ServletOutputStream outputStream = response.getOutputStream();) {
            byte []bytes = new byte[1024];
            int n;
            while((n = inputStream.read(bytes)) != -1)
            {
                outputStream.write(bytes,0,n);
            }
            log.info("用户在下载"+file.getAbsolutePath());
        } catch (Exception e){
            e.printStackTrace();
            log.info("下载文件出现严重异常!"+file.getName());
            ResponseResult.out(response,ResponseResult.error("文件下载出错，请稍后重试！"));
            return;
        }
    }

    @Override
    public ResponseResult downTest(Integer userId, Integer relevantReportId, String fileName) {
        return null;
    }

    @Override
    public void extendsFile(Integer oldIndexId,Integer newIndexId) {
        Index index=indexMapper.findIndexById(oldIndexId);
        Index newIndex=indexMapper.findIndexById(newIndexId);
        if(newIndex==null||index.getData()==null){
            return;
        }
        //port:22是连接linux传输,3389是连接windos传输
        Connection connection = new Connection("120.27.194.228",22);
        //客户端要存储的下载文件的路径可以自己随便定义--新的地址
        String path="/usr/src/index/static/upload/index/"+newIndex.getIndexId();
        File file=new File(path);
        file.mkdirs();
        String []filePath=Utils.split(index.getData());
        for(String x:filePath){
            String realPath=path+"/"+x;
            File newFile = new File(realPath);
            log.info(realPath);
            try(FileOutputStream fos = new FileOutputStream(newFile);) {
                connection.connect();
                boolean isAuthenticated = connection.authenticateWithPassword("root","Lishoujia3301");
                if(isAuthenticated){
                    SCPClient scpClient = connection.createSCPClient();
                    //从目标文件服务器下载文件
                    String oldIndexPath="/usr/src/index/static/upload/index/"+index.getIndexId()+"/"+x;
                    SCPInputStream sis = scpClient.get(oldIndexPath);
                    //先将远程服务器的文件下载到用户的电脑某个磁盘内
                    File f = new File("/usr/src/index/static/upload/index");
                    if(!f.exists()){
                        f.mkdirs();//不存在就创建文件夹
                    }
                    byte[] b = new byte[4096];
                    int i;
                    while ((i = sis.read(b)) != -1){
                        fos.write(b,0, i);
                    }
                    fos.flush();
                    fos.close();
                    sis.close();
                    connection.close();
                    log.info("download ok:  "+newIndex.getIndexId()+"-"+x);
                }else{
                    log.info("连接建立失败");
                }
            } catch (IOException e) {
                log.info(("下载文件异常="+e.toString()));
            }
        }
    }

    @Override
    public void fileToZip(Integer indexId, HttpServletResponse response) {
        Index index=indexMapper.findIndexById(indexId);
        if(index==null||index.getData()==null){
            return;
        }
        String[] fileName=Utils.split(index.getData());
        List<File> fileList=new ArrayList<>();
        String userPath1=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
        for(String x:fileName){
            String realPath1=System.getProperty("user.dir")+userPath1+"/"+x;
            fileList.add(new File(realPath1));
        }
        String fileZipPath=System.getProperty("user.dir")+userPath1+"/指标"+index.getIndexId()+".zip";
        //压缩========
        OutputStream os=null;
        try {
            os=new FileOutputStream(new File(fileZipPath));
            //调用压缩方法
            toZipUtils.toZip(fileList, os);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            //关闭流
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        //下载========
        log.info("打包完成:"+fileZipPath);
        File file = new File(fileZipPath);
        if (!file.exists()){
            log.info("文件不存在！！");
            ResponseResult.out(response,ResponseResult.error("文件不存在！"));
            return;
        }
        String zipName="";
        try{
            response.setCharacterEncoding("UTF-8");
            zipName = URLEncoder.encode("指标"+index.getIndexId()+".zip", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + zipName);
        }catch (Exception e){
            log.info(e.getMessage());
            ResponseResult.out(response,ResponseResult.error("编码错误，请稍后重试！"));
            log.info(zipName+"编码错误");
            return;
        }
        response.setContentType("application/octet-stream");
        try (InputStream inputStream = new FileInputStream(file);
             ServletOutputStream outputStream = response.getOutputStream();) {
            byte []bytes = new byte[1024];
            int n;
            while((n = inputStream.read(bytes)) != -1)
            {
                outputStream.write(bytes,0,n);
            }
            log.info("用户在下载"+file.getAbsolutePath());
        } catch (Exception e){
            e.printStackTrace();
            log.info("下载文件出现严重异常!"+file.getName());
            ResponseResult.out(response,ResponseResult.error("文件下载出错，请稍后重试！"));
            return;
        }
        //删除zip=======
        try{
            String userPath=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
            String realPath=System.getProperty("user.dir")+userPath;
            File file11=new File(realPath+"/"+zipName);
            if(file.exists()&&file.isFile()){
                Boolean q= file.delete();
                if(q){
                    log.info("删除成功");
                }else{
                    log.info("没有删除成功");
                }
            }else{
                log.info("文件不存在");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public ResponseResult deleteIndexFilesByIndexId(Integer indexId) {
        Index index=indexMapper.findIndexById(indexId);
        if(index==null){
            return ResponseResult.error("该指标不存在");
        }
        String userPath=UPLOAD_PATH_PREFIX+"index"+"/"+index.getIndexId();
        String realPath=System.getProperty("user.dir")+userPath;
        if(index.getData()!=null&&index.getData()!=""){
            String [] f=Utils.split(index.getData());
            for(String str:f){
                File file=new File(realPath+"/"+str);
                if(file.exists()&&file.isFile()) {
                    Boolean q = file.delete();
                    File file1=new File(realPath);
                    Boolean a= file1.delete();//删除文件夹
                    log.info(str+"删除结果: "+q);
                }else{
                    log.info("删除失败,文件不存在"+realPath+"/"+str);
                }
            }
        }
        return ResponseResult.success("成功");
    }

}
